<template>
  <div
    id="openlayersmap"
    :style="map_style"
    class="openlayers-map-container"
  >
    <div class="map-tip-div">
      <ul class="map-tip-content">
        <li>
          <font-awesome-icon
            icon="circle"
            size="sm"
            style="color: #8eff12;padding-right: 5px"
          />
          {{ $t('message.define.cu.state.2') }}：{{ stationList.filter(item => item.state === 2).length }}
        </li>
        <li>
          <font-awesome-icon
            icon="circle"
            size="sm"
            style="color: #57a600;padding-right: 5px"
          />
          {{ $t('message.define.cu.state.1') }}：{{ stationList.filter(item => item.state === 1).length }}
        </li>
        <li>
          <font-awesome-icon
            icon="circle"
            size="sm"
            style="color: #284805;padding-right: 5px"
          />
          {{ $t('message.define.cu.state.0') }}：{{ stationList.filter(item => item.state === 0).length }}
        </li>
      </ul>
    </div>
    <!--提示框-->
    <pop-up
      id="popup"
      :feature-data="popupData"
    />
    <div
      id="abnormal-pop"
      class="ol-popup"
      style="width: 300px"
    >
      <a
        href="#"
        id="abnormal-popup-closer"
        class="ol-popup-closer"
      />
      <div>
        <i
          class="el-icon-warning"
          style="color: orange"
        />
        {{ abnormalPopupMessage }}
      </div>
    </div>
  </div>
</template>

<script>
import PopUp from './PopUp'
// 引入css样式
import 'ol/ol.css'
import Map from 'ol/Map'
import View from 'ol/View'
import TileLayer from 'ol/layer/Tile'
// import ImageLayer from 'ol/layer/Image'
import TileWMS from 'ol/source/TileWMS'
// import ImageWMS from 'ol/source/ImageWMS'
import Feature from 'ol/Feature'
import { Point, LineString } from 'ol/geom'
import { fromLonLat } from 'ol/proj'
import { Style, Icon, Text, Fill, Stroke, Circle as CircleStyle } from 'ol/style'
import VectorSource from 'ol/source/Vector'
// import OSM from 'ol/source/OSM'
import VectorLayer from 'ol/layer/Vector'
import { defaults as defaultControls, FullScreen } from 'ol/control.js'
import Overlay from 'ol/Overlay'
// import { toStringHDMS } from 'ol/coordinate'
// import { getVectorContext } from 'ol/render'
// import smooth from 'chaikin-smooth'
function stringDivider (str, width, spaceReplacer) {
  if (str.length > width) {
    let p = width
    while (p > 0 && (str[p] !== ' ' && str[p] !== '-')) {
      p--
    }
    if (p > 0) {
      let left
      if (str.substring(p, p + 1) === '-') {
        left = str.substring(0, p + 1)
      } else {
        left = str.substring(0, p)
      }
      let right = str.substring(p + 1)
      return left + spaceReplacer + stringDivider(right, width, spaceReplacer)
    }
  }
  return str
}
export default {
  name: 'OpenLayers',
  components: {
    PopUp
  },
  watch: {
    changeStationStateData (data) {
      for (let item of data) {
        this.changeStationState(item)
      }
    },
    changeCommunicationLineData (data) {
      this.changeCommunicationLine(data)
    },
    changeOnLine (data) {
      this.changeOnline(data)
    },
    changeStationPosition: {
      deep: true,
      handler: function (station) {
        this.changeStationLonLat(station)
      }
    },
    // 退网异常的警告
    cuLogOut (data) {
      let station = this.stationList.find(stationItem => stationItem.id === data.station_id)
      if (station) this.cuLogOutNotify(data, station)
    }
  },
  computed: {
    stationList () {
      return this.$store.state.station.stationList
    },
    changeStationStateData () {
      return this.$store.state.station.openLayers.changeStationState
    },
    changeCommunicationLineData () {
      return this.$store.state.station.openLayers.changeCommunicationLine
    },
    changeOnLine () {
      return this.$store.state.station.openLayers.changeOnLine
    },
    changeStationPosition () {
      return this.$store.state.station.openLayers.changeStationPosition
    },
    cuLogOut () {
      return this.$store.state.cu.cuLogOutNotify
    }
  },
  data () {
    return {
      // map
      openlayers: null,
      vectorSource: null,
      vectorLayer: null,
      overlay: null,
      abnormalOverlay: null,
      abnormalPopupMessage: '',
      map_style: {},
      mapdata: {
        points: []
      },
      popupVisible: false,
      popupData: [],

      // accessLineReset: null,
      communicationLineReset: null,

      style: {
        'route': new Style({
          stroke: new Stroke({
            width: 6, color: [237, 212, 0, 0.8]
          })
        }),
        'geoMarker': new Style({
          image: new CircleStyle({
            radius: 7,
            fill: new Fill({ color: 'red' }),
            stroke: new Stroke({
              color: 'white', width: 2
            })
          })
        })
      },
      ii: true
    }
  },
  beforeCreate () {
    this.$store.commit('clearStationMapLine')
    this.$store.commit('clearChangeCommunicationLine')
  },
  mounted () {
    let self = this
    self.$nextTick(async () => {
      self.createOpenlayersMap()
      self.popInit()
      self.abnormalOverlayInit()
      await self.$store.dispatch(`getCenterStation`)
      await self.$store.dispatch(`getStationList`)
      self.initMapStationdata()
      await self.$store.dispatch(`getUsingTrafficChannel`)
      await self.$store.dispatch(`getUsingSubscribeFreqSegment`)
      self.$store.dispatch('initOpenlayersMapLine')
    })
  },
  methods: {
    createOpenlayersMap () {
      let self = this
      // 传入source
      self.vectorSource = new VectorSource({
        features: []
      })

      let format = 'image/jpeg'

      let rasterLayer = new TileLayer({
        source: new TileWMS({
          url: window.config.geoServerUrl,
          params: {
            'FORMAT': format,
            'VERSION': '1.1.1',
            tiled: true,
            'LAYERS': 'gadmWorld:gadmlayergroup',
            'exceptions': 'application/vnd.ogc.se_inimage',
            tilesOrigin: -180 + ',' + -90
          }
        })
      })

      // 设置vectorlayer的style

      self.vectorLayer = new VectorLayer({
        source: self.vectorSource
        // style: (feature) => self.style[feature.get('type')]
      })

      // let scaleLineControl = new ScaleLine()
      // scaleLineControl.setUnits('metric')

      self.openlayers = new Map({
        controls: defaultControls().extend([
          // scaleLineControl,
          new FullScreen()
        ]),
        layers: [rasterLayer, self.vectorLayer],
        target: document.getElementById('openlayersmap'),
        view: new View({
          center: fromLonLat([100.896372, 35.60240]),
          zoom: 4
        })
      })
      // self.vectorLayer.on('postrender', self.moveFeature)
      // self.openlayers.render()
    },
    popInit () {
      let self = this
      // 获取提示框组件
      const popContainer = document.getElementById('popup')
      const popCloser = document.getElementById('popup-closer')
      popCloser.onclick = function () {
        overlay.setPosition(undefined)
        popCloser.blur()
        self.popupData = []
        return false
      }

      /**
       * Create an overlay to anchor the popup to the map.
       */
      const overlay = new Overlay({
        element: popContainer,
        autoPan: true,
        autoPanAnimation: {
          duration: 250
        }
      })

      overlay.setPosition(undefined)

      self.openlayers.addOverlay(overlay)
      // 点击关闭按钮
      self.openlayers.on('click', evt => {
        let features = self.openlayers.getFeaturesAtPixel(
          evt.pixel
        )
        try {
          if (features.length) {
            let coordinate = features[0].getGeometry().getCoordinates()
            // 向pop组件传递数据
            self.popupData = features.map(featureItem => featureItem.getProperties().data).filter(featureItem => featureItem.node_type === 'station')
            if (!self.popupData.length) {
              overlay.setPosition(null)
              return
            }
            overlay.setPosition(coordinate)
          }
        } catch (e) {}
      })
      self.openlayers.on('pointermove', e => {
      // if (e.dragging) {
      //   $(element).popover('destroy');
      //   return;
      // }
        let pixel = self.openlayers.getEventPixel(e.originalEvent)
        let hit = self.openlayers.hasFeatureAtPixel(pixel)
        self.map_style = hit ? { cursor: 'pointer' } : {}
      // (this.map as any).getTarget().style.cursor = hit ? 'pointer' : '';
      })

      self.overlay = overlay
    },
    abnormalOverlayInit () {
      let self = this
      // 异常提示的overlay
      const abnormalPopContainer = document.getElementById('abnormal-pop')
      const abnormalPopCloser = document.getElementById('abnormal-popup-closer')
      abnormalPopCloser.onclick = function () {
        abnormalOverlay.setPosition(undefined)
        abnormalPopCloser.blur()
        self.abnormalPopupMessage = ''
        return false
      }
      const abnormalOverlay = new Overlay({
        element: abnormalPopContainer,
        autoPan: true,
        autoPanAnimation: {
          duration: 250
        }
      })
      abnormalOverlay.setPosition(undefined)

      self.openlayers.addOverlay(abnormalOverlay)

      self.abnormalOverlay = abnormalOverlay
    },
    getStationStyle (data) {
      // 设置样式
      let color = ''
      let zIndex = 0
      switch (data.state) {
        case 0:
          color = '#284805'
          zIndex = 1
          break
        case 1:
          color = '#57a600'
          zIndex = 2
          break
        case 2:
          color = '#8eff12'
          zIndex = 3
          break
        default:
          color = '#ae0004'
          zIndex = 1
      }
      return new Style({
        zIndex,
        image: new Icon({
          color: color,
          src: '/mapSource/img/dot.png',
          size: [16, 16]
        }),
        text: new Text({
          textAlign: 'left',
          // textBaseline: 'ideographic',
          // font: 'arial',
          text: stringDivider(data.name, 16, '\n'),
          fill: new Fill({ color: '#fff' }),
          // stroke: new Stroke({ color: '#fff', width: 1 }),
          offsetX: 12,
          offsetY: 0,
          backgroundFill: new Fill({ color: 'rgba(0,0,0,0.3)' }),
          // placement: placement,
          // maxAngle: maxAngle,
          // overflow: overflow,
          rotation: 0
        })
      })
    },
    initMapStationdata () {
      let self = this

      // 画点
      // let pointsArr = []
      for (let pointItem of self.stationList) {
        let pointFeature = new Feature({
          geometry: new Point(fromLonLat([pointItem.longitude, pointItem.latitude])),
          data: pointItem
        })
        // 设置id
        pointFeature.setId(pointItem.node_key)
        pointFeature.setStyle(self.getStationStyle(pointItem))
        // pointsArr.push(pointFeature)
        self.vectorSource.addFeature(pointFeature)
      }
      // self.vectorSource.addFeatures(pointsArr)
    },
    changeStationState (data) {
      let self = this
      let feature = self.vectorSource.getFeatureById(data.key)
      if (feature) feature.setStyle(self.getStationStyle(data))
    },
    // 当地球站经纬度变更时
    changeStationLonLat (data) {
      let self = this
      // 修改地球站坐标
      let feature = self.vectorSource.getFeatureById(data.node_key)
      if (feature) feature.setGeometry(new Point(fromLonLat([data.longitude, data.latitude])))
      if (data.state === 1) {
        // self.accessLineReset = data
        // self.$store.commit('deleteNetworkAccessLine', { id: data.id })
        self.$store.commit('pushNetworkAccessLine', {
          id: data.id
        })
      } else if (data.state === 2) {
        let featuresAll = self.vectorSource.getFeatures()
        for (let featureItem of featuresAll) {
          // 判断该feature是否为通信连线
          let featureId = featureItem.getId()
          if (featureId.startsWith('communicationline')) {
            let idArray = featureId.split('_')
            let ifContain = idArray.find(stationIdItem => stationIdItem === data.id.toString())
            // 如果地球站id存在于featureId中
            if (ifContain) {
              self.$store.commit('changeStationMapline', { caller_station_id: parseInt(idArray[1]), called_station_id: parseInt(idArray[2]) })
              self.$store.commit('pushNetworkAccessLine', {
                id: parseInt(idArray[1])
              })
              self.$store.commit('pushNetworkAccessLine', {
                id: parseInt(idArray[2])
              })
            }
          }
        }
      }
    },
    changeCommunicationLine (data) {
      let self = this
      if (data.operate === 'create') {
        self.createCommunicationLine(data)
      } else if (data.operate === 'delete') {
        self.deleteCommunicationline(data)
      }
    },
    createCommunicationLine (data) {
      let self = this
      if (data.coords[0][0] === data.coords[1][0] && data.coords[0][1] === data.coords[1][1]) return
      let arrPoints = [data.coords[0], self.getControlPoint(data.coords), data.coords[1]]
      let lineStringPoints = self.$service.createBezierCurvePoints(2, arrPoints)
      let lineStringFeature = new LineString(lineStringPoints.map(lineStringItem => fromLonLat(lineStringItem)))
      // 将line注入到feature中
      // let idArr = data.id.split('_')
      // self.deleteNetworkAccessline({ id: `online_${idArr[1]}`, station_id: idArr[1] })
      // self.deleteNetworkAccessline({ id: `online_${idArr[2]}`, station_id: idArr[2] })
      let changeCommunicationFeature = self.vectorSource.getFeatureById(data.id)
      if (changeCommunicationFeature) {
        changeCommunicationFeature.setGeometry(lineStringFeature)
        return
      }
      let lineFeature = new Feature({
        geometry: lineStringFeature,
        data
      })
      // 设置id 以及初始样式
      lineFeature.setId(data.id)
      self.vectorSource.addFeatures([lineFeature])
      lineFeature.setStyle(new Style({
        stroke: new Stroke({
          color: '#8eff12',
          // lineDash: [a * 2, a],
          // lineDashOffset: i ? 0 : a,
          width: 2
        })
      }))
      // 动态画线
    },
    // modifyMapLine (feature, station1, station2) {
    //   let coords = [
    //     [station1.longitude, station1.latitude],
    //     [station2.longitude, station2.latitude]
    //   ]
    //   if (coords[0][0] === coords[1][0] && coords[0][1] === coords[1][1]) return
    //   let arrPoints = [coords[0], self.getControlPoint(coords), coords[1]]
    //   let lineStringPoints = self.$service.createBezierCurvePoints(2, arrPoints)
    //   let lineStringFeature = new LineString(lineStringPoints.map(lineStringItem => fromLonLat(lineStringItem)))
    //   feature.setGeometry(lineStringFeature)
    // },
    deleteCommunicationline (data) {
      let self = this
      let deleteId = self.vectorSource.getFeatureById(data.id)
      if (deleteId) self.vectorSource.removeFeature(deleteId)
    },
    // 中垂线取点
    getControlPoint (coords) {
      let point0 = coords[0]
      let point1 = coords[1]
      let x1 = parseFloat(point0[0])
      let y1 = parseFloat(point0[1])
      let x2 = parseFloat(point1[0])
      let y2 = parseFloat(point1[1])
      let distanceAB = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2))
      let length = distanceAB / 6 // 中垂线上线段的高度
      // 如果斜率k为无穷大
      if (x1 === x2) {
        return [x1 + length, (y1 + y2) / 2]
      } else if (y1 === y2) { // k ===0
        return [(x1 + x2) / 2, y1 + length]
      } else { // 普通情况时
        let k1 = (y2 - y1) / (x2 - x1)
        // let k2 = -1 / k1
        // let b2 = yMid - k2 * xMid
        // 得出中垂线 y = k2x + b2
        // 直线上两点距离公式：length = 根号(k方+1)|x1-x2|=根号(1+(1/k方))|y1-y2|
        let h = length / (Math.sqrt(Math.pow(k1, 2) + 1))
        let w = h * Math.abs(k1)
        // let w = length / (Math.sqrt(Math.pow(k1, 2) + 1))
        // let h = w / Math.abs(k1)
        if (isNaN(h) || isNaN(w)) {
          throw new Error('control point computed error')
        }
        return [(x1 + x2) / 2 + w, (y1 + y2) / 2 + h]
      }
    },
    changeOnline (data) {
      let self = this
      if (data.operate === 'create') {
        self.createNetworkAccessLine(data)
      } else if (data.operate === 'delete') {
        self.deleteNetworkAccessline(data)
      }
    },
    createNetworkAccessLine (data) {
      let self = this
      // 如果两地球站坐标重复，直接返回，否则会造成计算错误
      if (data.coords[0][0] === data.coords[1][0] && data.coords[0][1] === data.coords[1][1]) return
      let arrPoints = [data.coords[0], self.getControlPoint(data.coords), data.coords[1]]
      let lineStringPoints = self.$service.createBezierCurvePoints(2, arrPoints)
      let lineStringFeature = new LineString(lineStringPoints.map(lineStringItem => fromLonLat(lineStringItem)))
      // 将line注入到feature中
      let lineFeature = new Feature({
        geometry: lineStringFeature
      })
      // 设置id 以及初始样式
      lineFeature.setId(data.id)
      let onlineFeature = self.vectorSource.getFeatureById(data.id)
      if (onlineFeature) {
        onlineFeature.setGeometry(lineStringFeature)
        return
      }
      self.vectorSource.addFeatures([lineFeature])
      lineFeature.setStyle(new Style({
        stroke: new Stroke({
          color: '#57a600',
          lineDash: [10, 5],
          width: 1
        })
      }))
    },
    deleteNetworkAccessline (data) {
      let self = this
      let deleteId = self.vectorSource.getFeatureById(data.id)
      if (deleteId) self.vectorSource.removeFeature(deleteId)
      // if (self.accessLineReset) {
      //   self.$store.commit('pushNetworkAccessLine', { id: data.station_id })
      //   self.accessLineReset = null
      // }
    },
    cuLogOutNotify (data, station) {
      let self = this
      let coordinate = [station.longitude, station.latitude]

      // self.abnormalPopupMessage = `地球站${station.name}的终端${data.device}退网`
      self.abnormalPopupMessage = self.$t('message.home.mapCard.stationLogoutNotify', { name: station.name, device: data.device })
      self.abnormalOverlay.setPosition(fromLonLat(coordinate))
      // 如果第二次事件发生时第一次定时器未完成，则注销上个定时器
      if (self.overlayTimeout) clearTimeout(self.overlayTimeout)
      self.overlayTimeout = setTimeout(() => {
        self.abnormalOverlay.setPosition(undefined)
        self.abnormalPopupMessage = ''
        self.overlayTimeout = null
      }, 6000)
    }
  }
}
</script>

<style lang="scss">
  @import "../style/def.scss";
  .openlayers-map-container{
    width: 100%;
    height: 100%;
    position: relative;
  }
  .ol-layer{
    canvas{
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
    }
  }
  .map-tip-div{
    position: absolute;
    border-radius: 4px;
    right: 15px;
    bottom: 15px;
    width: 180px;
    height: 100px;
    z-index: 10;
    color: $--color-text-primary;
    background-color: rgba(255, 255, 255, 0.68);
    .map-tip-title{
      padding-top: 10px;
    }
    .map-tip-content{
      text-align: left;
      padding-left: 20px;
    }
  }

  .ol-popup {
    position: absolute;
    background-color: white;
    -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
    filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
    padding: 15px;
    border-radius: 10px;
    border: 1px solid #cccccc;
    bottom: 12px;
    left: -50px;
    min-width: 240px;
  }
  .ol-popup:after, .ol-popup:before {
    top: 100%;
    border: solid transparent;
    content: " ";
    height: 0;
    width: 0;
    position: absolute;
    pointer-events: none;
  }
  .ol-popup:after {
    border-top-color: white;
    border-width: 10px;
    left: 48px;
    margin-left: -10px;
  }
  .ol-popup:before {
    border-top-color: #cccccc;
    border-width: 11px;
    left: 48px;
    margin-left: -11px;
  }
  .ol-popup-closer {
    text-decoration: none;
    position: absolute;
    top: 2px;
    right: 8px;
  }
  .ol-popup-closer:after {
    color: #c0c4cc;
    content: "✖";
  }

  .popup-col{
    text-align: left;
  }
</style>
